home *** CD-ROM | disk | FTP | other *** search
/ Free Software Collection: Marty 1 / FM Towns Marty 1 Free Software Collection.iso / tool / book / src / book.c < prev    next >
C/C++ Source or Header  |  1993-11-11  |  53KB  |  1,709 lines

  1. /*
  2.  *            <<< ひみつのBook >>>
  3.  *
  4.  *      High Speed Text Viewer for FM-TOWNS
  5. */
  6.  
  7. #include    <stdio.h>
  8. #include    <stdlib.h>
  9. #include    <stdarg.h>
  10. #include    <string.h>
  11. #include    <time.h>
  12. #include    <ctype.h>
  13. #include    <math.h>
  14. #include    <egb.h>
  15. #include    <mos.h>
  16. #include    <fmc.h>
  17. #include    <msdos.cf>
  18. #include    <exec.cf>
  19. #include    "event.h"
  20. #include    "book.h"
  21. #include    "file.h"
  22. #include    "init.h"
  23. #include    "lib.h"
  24. #include    "move.h"
  25. #include    "keyio.h"
  26. #include    "cons.h"
  27. #include    "menu.h"
  28. #include    "mouse.h"
  29.  
  30. /* #define DBG_DSP_MOVE_VAL */
  31. #define VOID_FUNC_POINTER   ((void(*)())0)
  32.  
  33. #define JUMP_LINE   50      /*  これ以上移動する場合は、再表示する  */
  34.  
  35. #define SPEED 333           /*  自動スクロールのインターバル  */
  36.  
  37. #define DOTS    3           /*  行間隔は 3種類  */
  38.  
  39. #define LNUM_X  (54*8)
  40. #define LNUM_Y  8
  41.  
  42. #define PITCH1  23
  43. #define BSIZE1  22
  44.  
  45. #define FNAM_X  12
  46. #define FNAM_Y  5
  47. #define CR_X    (FNAM_X+111)    /*  書式設定ボタン  */
  48. #define CR_Y    FNAM_Y
  49. #define SR_X    (CR_X+72)       /*  文字列検索ボタン  */
  50. #define SR_Y    FNAM_Y
  51.  
  52. #define TITLE_Y_MIN  0      /*  タイトルラインの開始位置  */
  53. #define TITLE_Y_MAX 31      /*  タイトルラインの最大位置  */
  54. #define TITLE_Y_SIZ (TITLE_Y_MAX-TITLE_Y_MIN+1)
  55.  
  56. #define SND_X   546         /*  読みあげボタン  */
  57. #define SND_Y   6
  58. #define FS_X    574         /*  ファイル・セレクタへ移動  */
  59. #define FS_Y    2
  60. #define EXIT_X  608         /*  直接終了するボタン  */
  61. #define EXIT_Y  2
  62.  
  63. #define STD_X2  650         /*  スクロール・バー部分の基準位置  */
  64. #define STD_Y2  84
  65. #define BSIZE2  20
  66. #define PITCH2  4
  67.  
  68. #define HUP_X    STD_X2      /*  加速 上スクロール・ボタン  */
  69. #define HUP_Y    STD_Y2
  70. #define HDOWN_X  STD_X2      /*  加速 下スクロール・ボタン  */
  71. #define HDOWN_Y  (STD_Y2+BSIZE2+PITCH2-4)
  72.  
  73. #define BAR_X   STD_X2      /*  スクロール・バー  */
  74. #define BAR_Y   (HDOWN_Y+BSIZE2+PITCH2-4)
  75. #define BAR_SIZ (200)
  76.  
  77. #define UP_X    STD_X2      /*  一定速度 上スクロール・ボタン  */
  78. #define UP_Y    (BAR_Y+BAR_SIZ+9)
  79. #define DOWN_X  STD_X2      /*  一定速度 下スクロール・ボタン  */
  80. #define DOWN_Y  (UP_Y+BSIZE2+PITCH2-2)
  81.  
  82.  
  83. #define S_XMIN   0              /*  猫の手スクロール通用範囲  */
  84. #define S_XSIZ   (STD_X2-4-S_XMIN)
  85. #define S_YMIN   32
  86. #define S_YSIZ   (MAX_VERTICAL-S_YMIN)
  87.  
  88.  
  89. #define RETVAL_EXIT 0   /*  mainへの戻り値  */
  90. #define RETVAL_NEXT 1   /*  EXITなら直接終了。NEXTならファイルセレクタ  */
  91.  
  92. static  dpl_t   dots[DOTS] =
  93.                     { {16,30,16,0,480}, {18,27,14,2,482}, {20,24,13,4,473} } ;
  94. static  dpl_t   *dot = dots ;       /*      初期値は0  */
  95.  
  96. static  short   offset = 0 ;        /*  テキスト画面のドット単位のズレ  */
  97.         short   auto_move = 0 ;         /*  自動スクロールの速度      */
  98. static  short   auto_move_value = 0 ;   /*  自動スクロールのドット数  */
  99. static  int     vram_ofs = 0 ;
  100. static  mevt_t  menu_event = MEv_NULL;
  101. static  short   vol_size = 0 ;
  102. static  HEADER  *now_file = NULL ;
  103.         short   can_use_snd = FALSE ;       /*  読み上げ機能の使用可不可  */
  104. static  short   wide = OFF ;                /*  幅広画面  */
  105.         short   max_horizon = MAX_HORIZON ; /*  最大水平位置  */
  106. static  char    tmp[256] ;
  107.  
  108. char    *msg[MAX_DSP_MSG] ;
  109. char    *btn[MAX_BTN_MSG] ;
  110.  
  111. int     writepage = PAGE0 ;     /*  書き込みページ  */
  112. int     page_ofs = 0x00000 ;
  113. char    gwork[ EgbWorkSize ] ;
  114.  
  115. extern  void    DSP_scr_bar( int init ) ;
  116. extern  void    dsp_menu( void ) ;
  117.  
  118.  
  119. void    init_screen( void )
  120. {
  121.     EGB_displayPage( gwork, 0, 0 ) ;    /*  表示を停止  */
  122.  
  123.     EGB_resolution( gwork, 0,3 ) ;
  124.     EGB_resolution( gwork, 1,3 ) ;
  125.  
  126.     wide_screen(wide);                          /*  横幅は拡大せず  */
  127.     vertical_screen( get_now_dpl()->lines ) ;   /*  縦のライン数を設定  */
  128.  
  129.     dsp_adr_set(vram_ofs + offset);
  130.  
  131.     /*  パレットの設定  */
  132.     cls( 0, 8 ) ;
  133.     EGB_palette( gwork, 0, (char *)&setup.palette ) ;
  134.     cls( 1, 0 ) ;
  135.     EGB_palette( gwork, 0, (char *)&setup.palette ) ;
  136.  
  137.     EGB_displayPage( gwork, 1, 3 ) ;    /*  表示を再開  */
  138. }
  139.  
  140. #if 1
  141. void    dsp_line(int y, char *buf, int bytes)
  142. {
  143. #define TYP_NORMAL  '\0'
  144. #define TYP_SPECIAL '\1'
  145. static  char    str[81];
  146. static  char    type[81];   /* 一般文字は 0、それ以外は 1 */
  147. auto    int     left;
  148. auto    int     i, pos;
  149. auto    char    *p, *q;
  150.  
  151.     if (bytes < 0)
  152.         return;
  153.  
  154.     memset(type, TYP_NORMAL, 80);   /* ノーマルで初期化 */
  155.  
  156.     for (q = type, p = str, i = pos = 0;
  157.             i < bytes; pos++, buf++, p++, q++, i++)
  158.     {
  159.         if (*buf < 0x20)        /*  制御コード  */
  160.         {
  161.             if (*buf == '\x0D' && *(buf+1) == '\x0A')   /*  改行コード  */
  162.             {
  163.                 *q = TYP_SPECIAL;
  164.                 break;
  165.             }
  166.             else if (*buf == '\t' && setup.tabsiz > 0)  /*  タブ  */
  167.             {
  168.                 left = setup.tabsiz - (pos % setup.tabsiz);
  169.                 while (pos < LINEMAX && --left > 0)
  170.                     *p++ = ' ', q++, pos++;
  171.                 *p = ' ';
  172.             }
  173.             else if (setup.disp_ctrl)               /*  一般制御コード  */
  174.             {
  175.                 *p++ = '^';
  176.                 *q++ = TYP_SPECIAL;
  177.                 *p = '@' + *buf;
  178.                 *q = TYP_SPECIAL;
  179.                 pos++;
  180.             }
  181.             else
  182.             {
  183.                 *p = *buf;
  184.                 *q = TYP_SPECIAL;
  185.             }
  186.         }
  187.         else                    /*  その他の文字  */
  188.         {
  189.             *p = *buf;
  190.         }
  191.     }
  192.     *p = '\0' ;
  193.  
  194.     y = X_OFFSET + ((y * dot->font + dot->ofs + vram_ofs) << 9) & 0x3FFFF;
  195.     putstr(y, str, pos, type);
  196.     if (buf[0] == '\x0D' && buf[1] == '\x0A' && setup.disp_cr && pos < LINEMAX)
  197.         wrtstr("\x1F", PAGE0,y+(pos<<2), _CR_COL,_BAK_COL,16);
  198.  
  199.     if (dot->spc > 0)
  200.         vram_part_clear(y+(16<<9)-X_OFFSET, dot->spc);
  201. }
  202. #else
  203. void    dsp_line(int y, char *buf, int bytes)
  204. {
  205. static  char    str[80];
  206. static  long    col[80];
  207. auto    int     left;
  208. auto    int     i, pos;
  209. auto    char    *p;
  210.  
  211.     if (bytes < 0)
  212.         return;
  213.  
  214.     for (p = str, i = pos = 0; i < bytes; pos++, buf++, p++, i++)
  215.     {
  216.         if (*buf < 0x20)        /*  制御コード  */
  217.         {
  218.             if (*buf == '\x0D' && *(buf+1) == '\x0A')   /*  改行コード  */
  219.             {
  220.                 if (setup.disp_cr) {
  221.                     col[pos++] = _CR_COL;
  222.                     *p = '\x1F';
  223.                 }
  224.                 break;
  225.             }
  226.             else if (*buf == '\t' && setup.tabsiz > 0)  /*  タブ  */
  227.             {
  228.                 left = setup.tabsiz - (pos % setup.tabsiz);
  229.                 while (pos < LINEMAX && --left > 0)
  230.                 {
  231.                     col[pos] = _CHR_COL;
  232.                     *p++ = ' ', pos++;
  233.                 }
  234.                 *p = ' ';
  235.                 col[pos] = _CHR_COL;
  236.             }
  237.             else if (setup.disp_ctrl)               /*  一般制御コード  */
  238.             {
  239.                 col[pos] = _CTRL_COL;
  240.                 *p++ = '^';
  241.                 *p = '@' + *buf;
  242.                 pos++;
  243.                 col[pos] = _CTRL_COL;
  244.             }
  245.             else
  246.             {
  247.                 *p = *buf;
  248.                 col[pos] = _CTRL_COL;
  249.             }
  250.         }
  251.         else                    /*  その他の文字  */
  252.         {
  253.             *p = *buf;
  254.             col[pos] = _CHR_COL;
  255.         }
  256.     }
  257.     *p = '\0';
  258.  
  259.     y = X_OFFSET + ((y * dot->font + dot->ofs + vram_ofs) << 9) & 0x3FFFF;
  260. extern void prtstr(char *str, long *col, int y, int col, int pos);
  261.     prtstr(str, col, y, _BAK_COL, pos);
  262.  
  263.     if (dot->spc > 0)
  264.         vram_part_clear(y+(16<<9)-X_OFFSET, dot->spc);
  265. }
  266. #endif
  267.  
  268. dpl_t   *get_now_dpl( void )    /*  外部ファイルに現在の行間隔を通知する  */
  269. {
  270.     return dot ;
  271. }
  272.  
  273.  
  274. static  void    dsp_file(int line)
  275. {
  276. HEADER  *hd = now_file;
  277. int     i, max = dot->max_y;
  278. LINPTR  *lp;
  279.  
  280.     if (hd->line_max > dot->max_y && line > (hd->line_max - dot->max_y))
  281.         line = hd->line_max - dot->max_y + 1;
  282.  
  283.     hd->line_now = hd->line_num = line;
  284.     hd->cur_pos = 0;
  285.     if ((line + dot->max_y - 1) > hd->line_max)
  286.     {
  287.         max = hd->line_max - line;
  288.         cls(0, 8);
  289.         DSP_writePage(gwork, 1);
  290.     }
  291.  
  292.     for (i = 0; i < max; i++)
  293.     {
  294.         lp = &(base[line/LINEPTRs]->ptr[line%LINEPTRs]) ;
  295.         dsp_line( i, lp->buf, lp->bytes ) ;
  296.         line++ ;
  297.     }
  298. }
  299.  
  300. static  void    _dsp_scrn(int line)
  301. {
  302. HEADER  *hd = now_file;
  303. int     i, last_num, now;
  304. LINPTR  *lp;
  305.  
  306.     last_num = hd->line_num;
  307.  
  308.     if ((i = line - hd->line_now) == 0)
  309.         return;
  310.     else if (abs(i) > JUMP_LINE)
  311.         dsp_file(line);
  312.     else
  313.     {
  314.         now = hd->line_now ;
  315.  
  316.         if (i > 0)
  317.         {
  318.             while (i-- > 0 && now < hd->line_max)
  319.             {
  320.                 now++;
  321.                 lp = &(base[now/LINEPTRs]->ptr[now%LINEPTRs]);
  322.                 if (++hd->cur_pos >= dot->max_y)
  323.                 {
  324.                     hd->cur_pos--;
  325.                     vram_ofs = (vram_ofs + dot->font) & 511;
  326.                     dsp_line(hd->cur_pos, lp->buf, lp->bytes);
  327.                 }
  328.             }
  329.         }
  330.         else
  331.         {
  332.             while (i++ < 0 && now > 0)
  333.             {
  334.                 now--;
  335.                 lp = &(base[now/LINEPTRs]->ptr[now%LINEPTRs]);
  336.                 if (--hd->cur_pos < 0)
  337.                 {
  338.                     hd->cur_pos++;
  339.                     vram_ofs = (vram_ofs - dot->font ) & 511;
  340.                     dsp_line(hd->cur_pos, lp->buf, lp->bytes);
  341.                 }
  342.             }
  343.         }
  344.         hd->line_now = now;
  345.         hd->line_num = hd->line_now - hd->cur_pos;
  346.     }
  347.  
  348.     if (last_num != hd->line_num)
  349.         DSP_scr_bar(FALSE);
  350. }
  351.  
  352. static  void    dsp_scrn(int line)
  353. {
  354.     _dsp_scrn(line);
  355.  
  356.     offset %= dot->font;
  357.  
  358.     if (auto_move == 0)     /* 自動スクロール中でなければ */
  359.         dsp_adr_set(vram_ofs + offset);
  360. }
  361.  
  362. static  void    snd_scrn( void )
  363. {
  364.     HEADER  *hd = now_file ;
  365.     LINPTR  *lp ;
  366.     int     pos = 1 ;
  367.     int     now = hd->line_num + 1 ;
  368.     int     max = now + dot->max_y - 2 ;
  369.     int     wrtpos = vram_ofs + dot->ofs ;
  370.  
  371.     mos_ptn( MOSCSR_CLOCK ) ;  /*  時計  */
  372.  
  373.     if( offset > 4 )
  374.         pos++, now++ ;
  375.     if( max > hd->line_max - 2 )
  376.         max = hd->line_max - 2 ;
  377.  
  378.     while( now < max )
  379.     {
  380.         lp = &(base[now/LINEPTRs]->ptr[now%LINEPTRs]) ;
  381.         if( snd_str( (wrtpos+pos*dot->font)&511, lp->buf, lp->bytes ) == ERR )
  382.             break ;
  383.         pos++, now++ ;
  384.     }
  385.  
  386.     mos_ptn( MOSCSR_FINGER ) ;  /*  ひと指し指  */
  387. }
  388.  
  389. static  void    AUTO_scroll(void)
  390. {
  391. HEADER  *hd = now_file;
  392.  
  393.     if (auto_move == 0)
  394.     {
  395.         EVT_unset_interval();       /*  自動スクロール停止  */
  396.         redisp_lnum();              /*  行番号の表示  */
  397.     }
  398.     else
  399.     {
  400.         offset += auto_move_value;
  401.  
  402.         if (offset >= dot->font)        /*  正方向スクロール  */
  403.             dsp_scrn(hd->line_now
  404.                + (dot->max_y - hd->cur_pos - 1) + (offset / dot->font));
  405.         else if (offset <= -dot->font) /*  逆方向スクロール  */
  406.             dsp_scrn(hd->line_now + (offset/dot->font) - hd->cur_pos);
  407.  
  408.         /*  末端まで来たら、停止する  */
  409.         if ((offset > 0 && hd->line_num + dot->max_y-1 >= hd->line_max) ||
  410.             (offset < 0 && hd->line_num == 0) || hd->line_max < dot->max_y)
  411.         {
  412.             auto_move = 0;
  413.             offset = 0;
  414.         }
  415.         dsp_adr_set(vram_ofs + offset);
  416.     }
  417. }
  418.  
  419. /*
  420.  *  自動スクロール開始
  421. */
  422. int     set_auto_scroll(int value)
  423. {
  424.     auto_move = value;
  425.  
  426.     return (auto_move_value = EVT_set_interval(129, value, AUTO_scroll));
  427. }
  428. /*
  429.  *  自動スクロール停止
  430. */
  431. void    unset_auto_scroll(void)
  432. {
  433.     auto_move = 0;
  434.  
  435.     EVT_unset_interval();
  436. }
  437.  
  438.  
  439. static  void    SCREEN_clip(REGS evt_t *ep, int x, int y, int sw)
  440. {
  441. static  int     last_y;
  442. static  int     repcount = 0;
  443.         int     value;
  444.         HEADER  *hd = now_file;
  445.  
  446.     sw = sw;    /*  意味なし。ワーニング回避  */
  447.     x = x;
  448.  
  449.     switch(ep->now)
  450.     {
  451.       case Ev_CLIP_MOS:
  452.         mos_ptn( MOSCSR_HAND ) ;
  453.         ep->now = Ev_REP_MOS ;
  454.  
  455.         MOS_horizon( ep->x1, ep->x2 ) ;     /*  移動範囲制限  */
  456.         MOS_vertical( ep->y1, ep->y2 ) ;
  457.  
  458.         unset_auto_scroll();    /*  自動スクロール停止  */
  459.  
  460.         last_y = y;
  461.         repcount = 0;
  462.  
  463.       case Ev_REP_MOS:     /*  猫の手スクロール  */
  464.         menu_event = MEv_NULL;
  465.  
  466.         if (++repcount < 20)
  467.             break;
  468.         repcount = 0;
  469.  
  470.         offset += ( last_y - y ) ;
  471.  
  472.         /*  行き過ぎたら、戻す  */
  473.         if ((offset > 0 && hd->line_num+dot->max_y-1 >= hd->line_max) ||
  474.             (offset < 0 && hd->line_num <= 0) || hd->line_max < dot->max_y)
  475.             dsp_adr_set(vram_ofs + (offset = 0));
  476.         else if (abs(offset) >= dot->font)      /*  行スクロール  */
  477.         {
  478.             if (offset > 0)                     /*  正方向スクロール  */
  479.                 dsp_scrn(hd->line_now +
  480.                         (dot->max_y - hd->cur_pos-1)+(offset/dot->font));
  481.             else                                /*  逆方向スクロール  */
  482.                 dsp_scrn(hd->line_now + (offset/dot->font) - hd->cur_pos);
  483.         }
  484.         else        /*  ドットスクロール  */
  485.             dsp_adr_set(vram_ofs + offset);
  486.  
  487.         last_y = y;
  488.  
  489.         break;
  490.  
  491.       case Ev_SELECT_MOS:      /*  自動スクロール開始  */
  492.         if ((value = (last_y - y)) != 0)
  493.         {
  494.             if (abs(value) > 5)
  495.                 value *= 4;
  496.             set_auto_scroll(value);
  497.         }
  498.  
  499.         MOS_horizon(  MIN_HORIZON, max_horizon  ) ;
  500.         MOS_vertical( MIN_VERTICAL, MAX_VERTICAL ) ;
  501.  
  502.         menu_event = MEv_NULL;
  503.         ep->now = Ev_ON_MOS ;
  504.       case Ev_ON_MOS:
  505.         mos_ptn( MOSCSR_FINGER ) ;
  506.         break ;
  507.     }
  508. }
  509.  
  510.  
  511. /*  スクロール・バーのクリップ  */
  512.  
  513. static  void    MOVE_clip( REGS evt_t *ep, int x, int y, int sw )
  514. {
  515.     x = x ;       /*  意味なし。ワーニングを避けるため  */
  516.     sw = sw ;
  517.  
  518.     switch( ep->now )
  519.     {
  520.       case Ev_CLIP_MOS:
  521.         mos_ptn( MOSCSR_HAND ) ;
  522.         MOS_horizon( ep->x1, ep->x2 ) ;
  523.         MOS_vertical( ep->y1, ep->y2 ) ;
  524.         ep->now = Ev_REP_MOS ;
  525.       case Ev_REP_MOS:
  526.         menu_event = MEv_NULL;
  527.         if (vol_size > 0)
  528.         {
  529.             offset = 0;
  530.             dsp_adr_set(vram_ofs);
  531.             dsp_scrn(((now_file->line_max) * ( y - ep->y1 ) ) / BAR_SIZ);
  532.         }
  533.         break ;
  534.  
  535.       case Ev_SELECT_MOS:
  536.         ep->now = Ev_ON_MOS ;
  537.       case Ev_OFF_MOS:
  538.       case Ev_MOVE_MOS:
  539.         MOS_horizon(  MIN_HORIZON, max_horizon  ) ;
  540.         MOS_vertical( MIN_VERTICAL, MAX_VERTICAL ) ;
  541.         menu_event = MEv_NULL;
  542.       case Ev_ON_MOS:
  543.         mos_ptn( MOSCSR_HAND ) ;
  544.         break ;
  545.     }
  546. }
  547.  
  548. /*  スクロール・バーの表示  */
  549.  
  550. static  void    DSP_scr_bar(int init)
  551. {
  552.     static  char    vol_ptn[(20+7)*(BAR_SIZ+7)];
  553.     static  int     last_pos = -1;
  554.     static  int     bar_siz;
  555.             HEADER  *hd = now_file;
  556.             int     bar_pos;
  557.             int     mx, my;
  558.  
  559.     /*  画面の幅が広くなく、しかも初期化でなければ、無視  */
  560.     if (wide == FALSE && init == FALSE)
  561.         return;
  562.  
  563.     if (init == TRUE)       /*  初期化と再初期化  */
  564.     {
  565.         if ((bar_siz = BAR_SIZ * (dot->max_y-1) / hd->line_max) >= BAR_SIZ)
  566.             bar_siz = BAR_SIZ-1;
  567.         vol_size = BAR_SIZ - bar_siz;
  568.  
  569.         bar_pos = hd->line_num * BAR_SIZ / hd->line_max ;
  570.  
  571.         MOS_disp( MOS_OFF ) ;   /*  常に消してから描画  */
  572.  
  573.         /*  地の部分を消去して、  */
  574.         pbox( BAR_X,BAR_Y,BAR_X+20,BAR_Y+BAR_SIZ+5, WIND_COL,WIND_COL ) ;
  575.         /*  中心軸を描く  */
  576.         pbox( BAR_X+8,BAR_Y+2, BAR_X+12,BAR_Y+BAR_SIZ+3, BOX2_COL,BOX1_COL ) ;
  577.  
  578.         /*  描いた背景を保存する  */
  579.         DSP_getBlock( BAR_X,BAR_Y+3, 20,BAR_SIZ+3, vol_ptn ) ;
  580.  
  581.         pbox(BAR_X+2,BAR_Y+3+bar_pos, BAR_X+18,BAR_Y+3+bar_pos+bar_siz, 15,15);
  582.     }
  583.     else
  584.     {
  585.         /*  移動先を計算し、表示上の差がなければ描画はしない  */
  586.         if ((bar_pos = hd->line_num * BAR_SIZ / hd->line_max) == last_pos)
  587.             return;
  588.  
  589.         /*  スクロール・バーにかぶってたら、マウスカーソルを消す  */
  590.         mos_rdpos(NULL, &mx,&my);
  591.         if (mx > BAR_X - 16 && my > BAR_Y-16 && my < BAR_Y+BAR_SIZ+4)
  592.             MOS_disp(MOS_OFF);
  593.  
  594.         /*  スクロール・バーの差分だけを描く  */
  595.         if ((bar_pos - last_pos) < 0)
  596.         {
  597.             DSP_putBlock(BAR_X,BAR_Y+3+bar_pos+bar_siz+1,
  598.                              20,last_pos-bar_pos-1, vol_ptn);
  599.             if (last_pos - bar_pos > bar_siz)
  600.                 last_pos = bar_pos + bar_siz;
  601.             pbox(BAR_X+2,BAR_Y+3+bar_pos,
  602.                                     BAR_X+18,BAR_Y+3+last_pos, 15,15);
  603.         }
  604.         else
  605.         {
  606.             DSP_putBlock(BAR_X,BAR_Y+3+last_pos,
  607.                              20,bar_pos-last_pos-1, vol_ptn);
  608.             if (bar_pos - last_pos > bar_siz)
  609.                 last_pos = bar_pos - bar_siz;
  610.             pbox(BAR_X+2,BAR_Y+3+last_pos+bar_siz,
  611.                                 BAR_X+18,BAR_Y+3+bar_pos+bar_siz, 15,15);
  612.         }
  613.     }
  614.     last_pos = bar_pos;
  615.  
  616.     MOS_disp(MOS_ON);
  617. }
  618.  
  619. static  void    set_wide_screen(int flag)
  620. {
  621.     if ((wide = flag) == TRUE)
  622.         MOS_horizon(MIN_HORIZON, (max_horizon = MAX_HORIZON));
  623.     else
  624.         MOS_horizon(MIN_HORIZON, (max_horizon = MAX_HORIZON2));
  625.     MOS_vertical(MIN_VERTICAL, MAX_VERTICAL);
  626.     wide_screen(wide);
  627. }
  628.  
  629. /*  右クリック時の動作  */
  630. static  void    RIGHT_click(void)
  631. {
  632.     set_wide_screen(!wide);
  633.     DSP_scr_bar(FALSE);
  634. }
  635.  
  636. static  void    MENU_clip( REGS evt_t *ep, int x, int y, int sw )
  637. {
  638.     static  int     lastev = -1 ;
  639.     static  int     repcount = 0 ;
  640.     auto    int     now ;
  641.  
  642.     x = x, y = y, sw = sw ;    /*  意味なし。ワーニングを避けるため  */
  643.  
  644.     now = ep->now ;
  645.  
  646.     switch( now )
  647.     {
  648.       case Ev_CLIP_MOS:
  649.         mos_ptn( MOSCSR_HAND ) ;
  650.         if( !isclip( ep ) )
  651.             DSP_clip_on( ep ) ;
  652.         if( isrepeat( ep ) )
  653.         {
  654.             menu_event = ep->no ;
  655.             ep->now = Ev_REP_MOS ;
  656.         }
  657.         break ;
  658.  
  659.       case Ev_REP_MOS:
  660.         if( lastev != Ev_REP_MOS )
  661.             repcount = 0 ;
  662.         else if( (++repcount) > 300 )
  663.             menu_event = ep->no, repcount = 0 ;
  664.         break ;
  665.  
  666.       case Ev_DOLACK_MOS:
  667.         ep->now = Ev_NON ;
  668.       case Ev_MOVE_MOS:
  669.         if( !isclip( ep ) )
  670.             DSP_clip_off( ep ) ;
  671.       case Ev_OFF_MOS:
  672.         mos_ptn( MOSCSR_FINGER ) ;
  673.         break ;
  674.  
  675.       case Ev_SELECT_MOS:
  676.         if( !isrepeat( ep ) )
  677.             menu_event = ep->no ;
  678.         if( !isclip( ep ) )
  679.             DSP_clip_off( ep ) ;
  680.         ep->now = Ev_ON_MOS ;
  681.       case Ev_ON_MOS:
  682.         mos_ptn( MOSCSR_HAND ) ;
  683.         break ;
  684.     }
  685.  
  686.     lastev = now ;
  687. }
  688.  
  689. /*
  690.  *  タイトル部分を退避する
  691. */
  692. void    title_backup(int sw)
  693. {
  694.     static  char    buf[TITLE_Y_SIZ*640/2];
  695.  
  696.     MOS_disp(MOS_OFF);
  697.     if (sw == ON)
  698.         DSP_getBlock(X_DOTOFS,TITLE_Y_MIN, 639,TITLE_Y_MAX, buf);
  699.     else
  700.         DSP_putBlock(X_DOTOFS,TITLE_Y_MIN, 639,TITLE_Y_MAX, buf);
  701.     MOS_disp(MOS_ON);
  702. }
  703.  
  704. /*  テキスト表示状態のメニュー描画と、イベント登録  */
  705.  
  706. static  void    dsp_menu( void )
  707. {
  708.     EVT_reset() ;
  709.  
  710.     /*  上のラインの表示  */
  711.     dsp_box( X_DOTOFS,TITLE_Y_MIN, 639+X_DOTOFS,TITLE_Y_MAX,
  712.                                                 BOX1_COL,BOX2_COL,WIND_COL ) ;
  713.  
  714.     /*  Version & Edition の表示  */
  715.     dsp_box( 270,5, 370,25, BLACK_l,BLACK_l,WIND_COL ) ;
  716.     *tmp = '\0';
  717.     _strcats(80, tmp, "BOOK v", version, NULL);
  718.     wrt(tmp, 280,8, BLACK_l,WIND_COL, 16);
  719.     EVT_set_node(270,5, 100,20, 128,MENU_clip,MEv_DOSCMD, CLIP|REP);
  720.  
  721.     /*  表示書式  */
  722.     BTN_set( CR_X,CR_Y, 46,BSIZE2, WIND_COL, 128,MENU_clip,MEv_FORM, NOP ) ;
  723.     wrt("書式", CR_X+8,CR_Y+2, STD_COL,WIND_COL, 16);
  724.  
  725.     /*  文字列検索  */
  726.     BTN_set( SR_X,SR_Y, 46,BSIZE2, WIND_COL, 128,MENU_clip,MEv_SEARCH, NOP ) ;
  727.     wrt( "検索", SR_X+8,SR_Y+2, STD_COL,WIND_COL, 16 ) ;
  728.  
  729.     /*  ファイル名  */
  730.     BTN_set( FNAM_X,FNAM_Y, 12*8+8,BSIZE2,
  731.                                 WIND_COL, 128,MENU_clip,MEv_FULLPATH, REP ) ;
  732.     wrt( now_file->name, FNAM_X+4+(12-strlen(now_file->name))*4,
  733.                                             FNAM_Y+2, STD_COL,WIND_COL, 16 ) ;
  734.  
  735.     /*  [音]ボタンの表示  */
  736.     if( can_use_snd == TRUE )
  737.     {
  738.         BTN_set( SND_X,SND_Y, 22,20, WIND_COL, 128,MENU_clip,MEv_SND, NOP ) ;
  739.         DSP_ptnColor( SND_X+2,SND_Y+2, 31,31, ptn_snd, 1 ) ;
  740.     }
  741.  
  742.     /*  [FS] ボタンの表示  */
  743.     BTN_set( FS_X,FS_Y, 28,27, WIND_COL, 128,MENU_clip,MEv_FS, NOP ) ;
  744.     DSP_ptnColor( FS_X,FS_Y, 31,31, ptn_file, 1 ) ;
  745.  
  746.     /*  [EXIT] ボタンの表示  */
  747.     BTN_set( EXIT_X,EXIT_Y, 28,27, WIND_COL, 128,MENU_clip,MEv_EXIT, NOP ) ;
  748.     DSP_ptnColor( EXIT_X,EXIT_Y, 31,31, ptn_door, 1 ) ;
  749.  
  750.  
  751.     /*  右側のスクロール・バー表示  */
  752.     dsp_box( HUP_X-2,HUP_Y-2, DOWN_X+BSIZE2+2, DOWN_Y+BSIZE2+2,
  753.                                                 BOX1_COL,BOX2_COL,WIND_COL);
  754.     EVT_set_node(BAR_X+1,BAR_Y+3, 19,BAR_SIZ, 128,MOVE_clip,MEv_DUMMY, NOP);
  755.  
  756.     BTN_set( HUP_X,HUP_Y, BSIZE2,BSIZE2-3, WIND_COL,
  757.                                                 128,MENU_clip,MEv_vDOWN, REP);
  758.     wrt( "▲", HUP_X+2,HUP_Y+2+6, STD_COL,WIND_COL,8 ) ;
  759.     wrt( "▲", HUP_X+2,HUP_Y+2, STD_COL,WIND_COL,8 ) ;
  760.  
  761.     BTN_set( HDOWN_X,HDOWN_Y, BSIZE2,BSIZE2-3, WIND_COL,
  762.                                                 128,MENU_clip,MEv_vUP, REP);
  763.     wrt( "▼", HDOWN_X+2,HDOWN_Y+2, STD_COL,WIND_COL,8);
  764.     wrt( "▼", HDOWN_X+2,HDOWN_Y+2+6, STD_COL,WIND_COL,8);
  765.  
  766.     BTN_set( UP_X,UP_Y, BSIZE2,BSIZE2-1, WIND_COL,
  767.                                             128,MENU_clip,MEv_mDOWN, REP ) ;
  768.     wrt( "▲", UP_X+2,UP_Y+2, STD_COL,WIND_COL,16 ) ;
  769.  
  770.     BTN_set( DOWN_X,DOWN_Y, BSIZE2,BSIZE2-1, WIND_COL,
  771.                                             128,MENU_clip,MEv_mUP, REP ) ;
  772.     wrt( "▼", DOWN_X+2,DOWN_Y+1, STD_COL,WIND_COL,16 ) ;
  773.  
  774.     /*  最大行数  */
  775. /*    sprintf( tmp, "     0/%d", now_file->line_max-1 ) ; */
  776.     strcpy( tmp, "     0/" ) ;
  777.     strcat( tmp, formdigitL( now_file->line_max-1, 6, NO ) ) ;
  778.     wrt( tmp, LNUM_X,LNUM_Y, STD_COL,WIND_COL, 16 ) ;
  779.  
  780.     DSP_scr_bar(TRUE);          /*  スクロール・バーの表示  */
  781.     EVT_set_cancel(127, RIGHT_click);       /*  右クリック  */
  782.  
  783.     EVT_set_node(S_XMIN,S_YMIN, S_XSIZ,S_YSIZ,      /*  画面を掴む  */
  784.                                        129,SCREEN_clip,MEv_DUMMY, LOCK);
  785. }
  786.  
  787. /*  画面をテキスト表示状態にする  */
  788. static  void    set_screen(int mos_disp)
  789. {
  790.     MOS_disp(MOS_OFF);
  791.     mos_backup(ON);
  792.     MOS_writePage(1);
  793.  
  794.     set_wide_screen(wide);          /*  横幅を設定  */
  795.     mos_backup(OFF);
  796.  
  797.     EGB_displayPage( gwork, 1, 3 ) ; /*  両ページを表示  */
  798.     MOS_disp( mos_disp ) ;
  799. }
  800.  
  801. /*  画面をテキスト表示状態にする  */
  802. static  void    set_text_screen(int lnum)
  803. {
  804.     MOS_disp( MOS_OFF ) ;
  805.  
  806.     cls( 0, 8 ) ;
  807.     cls( 1, 0 ) ;
  808.  
  809.     set_screen( MOS_OFF ) ;
  810.     dsp_menu();
  811.     dsp_file(lnum);
  812.  
  813.     redisp_lnum();
  814.     DSP_scr_bar(FALSE);
  815.  
  816.     mos_ptn( MOSCSR_FINGER ) ;
  817.     MOS_disp( MOS_ON ) ;
  818. }
  819. /*  ファイルセレクタ画面にする  */
  820. static  void    set_fs_screen( void )
  821. {
  822.     MOS_disp(MOS_OFF);
  823.  
  824.     set_wide_screen(OFF);       /*  横幅を復元  */
  825.     cls(1, 0);                  /*  画面消去  */
  826.     cls(0, 0);
  827.  
  828.     unset_auto_scroll();        /* 自動スクロール停止 */
  829.  
  830.     vram_ofs = 0;
  831.     dsp_adr_set(0);
  832.  
  833.     EGB_displayPage(gwork, 1, 3);   /*  両ページを表示  */
  834. }
  835.  
  836. static  HEADER  *read_file( char *file, readtype_t reform, int lnum )
  837. {
  838.     /*  画面の準備  */
  839.     void    prt_center(char *str, int y)
  840.     {
  841.     int     siz;
  842.  
  843.         siz = strlen(str) * 4 + 16;
  844.         pbox(320-siz,y, 320+siz, y+39, WIND_COL,WIND_COL);
  845.         wrt(str, 320-siz+16,y+12, STD_COL,WIND_COL, 16);
  846.     }
  847.  
  848.     DSP_writePage(gwork, 1);
  849.     MOS_disp(MOS_OFF);
  850.  
  851.     if (reform == FILE_READ)
  852.     {
  853.         set_screen(MOS_OFF);
  854.  
  855.         /* EGB_displayPage(gwork, 1, 0); */ /* 両ページを非表示 */
  856.         cls(1, 0);
  857.         cls(0, 8);
  858.  
  859.         prt_center(file, 150);
  860.         prt_center("ファイルを読み込んでいます", 230);
  861.  
  862.         /*EGB_displayPage(gwork, 1, 3); */  /* 両ページを表示 */
  863.     }
  864.     else
  865.         prt_center("しばらくお待ちください", 220);
  866.     mos_ptn(MOSCSR_CLOCK);
  867.     MOS_disp(MOS_ON);
  868.  
  869.  
  870.     /*  実際の読み込み処理をやってもらう  */
  871.     if ((now_file = read_sub(file, reform)) == NULL)
  872.         return NULL;
  873.  
  874.     /*  画面の準備  */
  875.     set_text_screen(lnum);
  876.  
  877.     return now_file;
  878. }
  879.  
  880. int     redisp_lnum(void)
  881. {
  882. #define COLUMN 6
  883. static  char    buf[COLUMN+1];
  884. static  int     last = 0;
  885.         int     i, mx, my;
  886.         int     number = now_file->line_num;
  887.  
  888.     if ((auto_move != 0 || kb_check()) && abs(last-number) < 10)
  889.         return FALSE;
  890.     last = number;
  891.  
  892.     buf[COLUMN] = '\0';
  893.     for (i = COLUMN-1; i >= 0; i--)
  894.     {
  895.         buf[i] = '0' + (number % 10);
  896.         if ((number /= 10) == 0)
  897.             break;
  898.     }
  899.     while (--i >= 0)
  900.         buf[i] = ' ';
  901.  
  902.     mos_rdpos(NULL, &mx,&my);
  903.     if (mx > LNUM_X-16 && mx < LNUM_X+(COLUMN*8) &&
  904.         my > LNUM_Y-16 && my < LNUM_Y+16)
  905.         MOS_disp(MOS_OFF);
  906.     wrt(buf, LNUM_X,LNUM_Y, STD_COL,WIND_COL,16);
  907.     MOS_disp(MOS_ON);
  908.  
  909.     return TRUE;
  910. }
  911.  
  912. static  void    display_fullpathlist(char *file)
  913. {
  914. int     num;
  915. evt_t   *ep;
  916. int     org_ctrl = setup.disp_ctrl;
  917. int     org_tab = setup.tabsiz;
  918.  
  919. /*  msg[0] = "フルパス表示";  */
  920.     msg[0] = "フルパス\x95\x5C示";
  921.     msg[1] = "環境再初期化";
  922.     msg[2] = "About...";
  923.     msg[3] = NULL;
  924.  
  925.     ep = EVT_get_node(128, MEv_FULLPATH);
  926.  
  927.     num = select_drag(ep, TRUE, ep->x1,28, 160, msg, "");
  928.  
  929.     DSP_clip_off(ep = EVT_get_node(128, MEv_FULLPATH));
  930.     ep->now = Ev_NON;
  931.  
  932.     switch(num)
  933.     {
  934.       case 0:   /*  フルパス表示  */
  935.         {
  936. static  int     xc = 0, yc = 0; /*  position  */
  937.             msg[0] = file;
  938.             msg[1] = NULL;
  939.             btn[0] = "確  認";
  940.             btn[1] = NULL;
  941.             select_mode(" 現在ファイル ", msg, btn, 26, &xc,&yc);
  942.         }
  943.         break;
  944.  
  945.       case 1:   /*  BOOK.CFG再読み込み  */
  946.         excmd_init();
  947.         wc_init();
  948.         configuration(config);
  949.         if (org_ctrl != setup.disp_ctrl || org_tab != setup.tabsiz)
  950.             read_file(file, FILE_REFORM, now_file->line_num);
  951.         init_screen();
  952.         set_text_screen(now_file->line_num);
  953.         break;
  954.  
  955.       case 2:   /*  バージョン表示  */
  956.         {
  957. static  int     xc = MENU_CENTERING, yc = 0; /*  position  */
  958.             msg[0] = "High Speed Text Viewer for FM-TOWNS";
  959.             msg[1] = "presented by MIYAZAKI & sugi  1990-93";
  960.             *tmp = '\0';
  961.             _strcats(80, tmp, "version ", _version, "   ", date, NULL);
  962.             msg[2] = tmp;
  963.             msg[3] = NULL;
  964.             btn[0] = "確  認";
  965.             btn[1] = NULL;
  966.             select_mode("  <<< ひみつのBook >>>  ", msg, btn, 28, &xc, &yc);
  967.             break;
  968.         }
  969.     }
  970. }
  971.  
  972. int     findstr( char *a, char *str, int len, int pos, int max )
  973. {
  974.     int     ch = tolower( *str ) ;
  975.  
  976.     a += pos ;
  977.  
  978.     if (setup.caps)     /*  大小文字区別  */
  979.     {
  980.         for( ; max-- > 0 ; a++, pos++ )
  981.             if( *a == *str && memcmp( a, str, len ) == 0 )
  982.                 return pos ;
  983.     }
  984.     else
  985.     {
  986.         for( ; max-- > 0 ; a++, pos++ )
  987.             if( tolower( *a ) == ch && jmemicmp( a, str, len ) == 0 )
  988.                 return pos ;
  989.     }
  990.     return -1 ;
  991. }
  992. int     findrstr( char *a, char *str, int len, int pos, int max )
  993. {
  994.     int     ch = tolower( *str ) ;
  995.  
  996.     if( pos >= max )
  997.         pos = max - 1 ;
  998.     a += pos ;
  999.  
  1000.     if (setup.caps)     /*  大小文字区別  */
  1001.     {
  1002.         for( ; pos >= 0 ; a--, pos-- )
  1003.             if( *a == *str && memcmp( a, str, len ) == 0 )
  1004.                 return pos ;
  1005.     }
  1006.     else
  1007.     {
  1008.         for( ; pos >= 0 ; a--, pos-- )
  1009.             if( tolower( *a ) == ch && jmemicmp( a, str, len ) == 0 )
  1010.                 return pos ;
  1011.     }
  1012.  
  1013.     return -1 ;
  1014. }
  1015. int     get_nowline( void ) /*  外部ファイルに現在の表示開始行を通知する  */
  1016. {
  1017.     return now_file->line_num ;
  1018. }
  1019.  
  1020. /*  行内のバイト位置から、文字位置を計算する  */
  1021.  
  1022. int     calc_pos( char *str, int pos )
  1023. {
  1024.     int     cnt = 0 ;
  1025.  
  1026.     while( pos-- > 0 )
  1027.     {
  1028.         if( *str < 0x20 )                           /*  制御コード  */
  1029.         {
  1030.             if( *str == '\x0D' && *(str+1) == '\x0A' ) /*  改行コード  */
  1031.                 break ;
  1032.             else if( *str == '\t' && setup.tabsiz > 0 )   /*  タブ  */
  1033.                 cnt += setup.tabsiz - ( cnt % setup.tabsiz ) ;
  1034.             else if (setup.disp_ctrl)               /*  一般制御コード  */
  1035.                 cnt += 2 ;
  1036.             else
  1037.                 cnt++ ;
  1038.         }
  1039.         else                                        /*  その他の文字  */
  1040.             cnt++ ;
  1041.         str++ ;
  1042.     }
  1043.     return cnt ;
  1044. }
  1045.  
  1046. /*  行内のバイト位置・表示開始位置・文字列長から表示桁数を計算する  */
  1047.  
  1048. int     calc_len( char *str, int pos, int xpos, int len )
  1049. {
  1050.     int     cnt = 0 ;
  1051.  
  1052.     str += pos ;
  1053.  
  1054.     while( len-- > 0 )
  1055.     {
  1056.         if( *str < 0x20 )                           /*  制御コード  */
  1057.         {
  1058.             if( *str == '\x0D' && *(str+1) == '\x0A' ) /*  改行コード  */
  1059.                 cnt++, str++, len-- ;
  1060.             else if( *str == '\t' && setup.tabsiz > 0 )   /*  タブ  */
  1061.                 cnt += setup.tabsiz - ( (xpos+cnt) % setup.tabsiz ) ;
  1062.             else if( *str == '\x0A' && pos > 0 && *(str-1) == '\x0D' )
  1063.                 cnt++ ;                             /*  0x0A から検索した時  */
  1064.             else if (setup.disp_ctrl)               /*  一般制御コード  */
  1065.                 cnt += 2 ;
  1066.             else
  1067.                 cnt++ ;
  1068.         }
  1069.         else                                        /*  その他の文字  */
  1070.             cnt++ ;
  1071.         str++ ;
  1072.     }
  1073.     return cnt ;
  1074. }
  1075.  
  1076. static  void    search_str( void )
  1077. {
  1078.     void    line( int x, int y, int xs )
  1079.     {
  1080.         int X( x ) { return x > XMAX ? XMAX : x ; }
  1081.  
  1082.         DSP_writePage( gwork, 0 ) ;
  1083.         EGB_writeMode( gwork, MODE_XOR ) ;
  1084.         dsp_box_clip( XMIN,y,    XMAX,y,    2,2,2 ) ;
  1085.         dsp_box_clip( XMIN,y+16, XMAX,y+16, 2,2,2 ) ;
  1086.         dsp_box_clip( x,y+1,X(x+xs-1),y+15, 2,2,2 ) ;
  1087.         y += dot->font ;
  1088.         if( x+xs-1 > XMAX ) /*  2行に渡っている  */
  1089.             dsp_box_clip( XMIN,y, x+xs-1-XMAX+XMIN,y+16, 2,2,2 ) ;
  1090.         DSP_writePage( gwork, 1 ) ;
  1091.         EGB_writeMode( gwork, MODE_PSET ) ;
  1092.     }
  1093.     void    cnv_str( char *str, int len )
  1094.     {
  1095.         char    *p, tmpbuf[80] ;
  1096.         int     i ;
  1097.  
  1098.         /*  制御文字を一般バイナリ形式から特殊表現形式に変換する  */
  1099.         for( i=0, p=tmpbuf ; i < len ; p++, i++ )
  1100.         {
  1101.             if( str[i] < 0x20 )
  1102.                 *p = CTRL_PRE, *++p = 0x40 | str[i] ;
  1103.             else
  1104.                 *p = str[i] ;
  1105.         }
  1106.         *p = '\0' ;
  1107.         strcpy( str, tmpbuf ) ;
  1108.     }
  1109.     int     recnv_str( char *str )
  1110.     {
  1111.         char    *p, tmpbuf[80] ;
  1112.         int     len ;
  1113.  
  1114.         /*  制御文字を特殊表現形式から一般バイナリ形式に変換する  */
  1115.         for( len=0, p=str ; *p ; p++, len++ )
  1116.         {
  1117.             if( *p == CTRL_PRE )
  1118.                 tmpbuf[len] = *++p - 0x40 ;
  1119.             else
  1120.                 tmpbuf[len] = *p ;
  1121.         }
  1122.         memcpy( str, tmpbuf, len ) ;
  1123.  
  1124.         return len ;
  1125.     }
  1126.     static  char    str[50] = "" ;
  1127.     static  int     str_len = 0 ;
  1128.     static  int     menu_x = 600, menu_y = 0 ;
  1129.             char    laststr[50] = "" ;
  1130.             char    type[82] ;      /*  ANK, 漢字1/2byte識別  */
  1131.             LINPTR  *lp = NULL ;
  1132.             int     diff = 0, lnum=0 ;
  1133.             int     line_lnum=0, minline=0, maxline=0 /*, line_lineofs */;
  1134.             int     size_x, size_y ;
  1135.             int     x=0, xs=0, y=0, pos=0, forward ;
  1136.             int     newline = TRUE, found = FALSE ;
  1137.             int     lastcaps = setup.caps ;
  1138.             mevt_t  func, lastfunc = MEv_NULL;
  1139.             HEADER  *hd = now_file ;
  1140.  
  1141.     while( 1 )
  1142.     {
  1143.         do {
  1144.             cnv_str(str, str_len);      /*  一般バイナリ形式→特殊表現形式  */
  1145.             func = input_string(str, NO, &menu_x,&menu_y, &size_x,&size_y,
  1146.                                                             &minline,&maxline);
  1147.             str_len = recnv_str(str);   /*  特殊表現形式→一般バイナリ形式  */
  1148.         } while (func != MEv_CANCEL && str_len == 0);
  1149.  
  1150.         if( found == TRUE &&
  1151.             minline >= line_lnum-dot->max_y+1 && maxline-1 <= line_lnum )
  1152.                 line(x, y, xs);
  1153.         if (func == MEv_CANCEL)
  1154.             break;
  1155.  
  1156.         if (func == MEv_FfSEARCH || func == MEv_ErSEARCH)
  1157.         {
  1158.             if (func != lastfunc)
  1159.             {
  1160.                 newline = TRUE;
  1161.                 if (func == MEv_FfSEARCH)   /*  ファイルの先頭から進む  */
  1162.                     pos = lnum = 0;
  1163.                 else if (func == MEv_ErSEARCH)  /*  ファイルの末端から戻る  */
  1164.                     pos = LINEMAX-1, lnum = hd->line_max - 1;
  1165.             }
  1166.         }
  1167.         else if (((lnum < 1 || lnum > hd->line_max-1) &&
  1168.                  (memcmp(laststr, str, str_len) != 0 ||
  1169.                               func != lastfunc || lastcaps != setup.caps)) ||
  1170.                  (found == TRUE && (hd->line_num > line_lnum ||
  1171.                                     hd->line_num < line_lnum-dot->max_y+2)))
  1172.         {
  1173.             newline = TRUE;
  1174.  
  1175.             if (func == MEv_fSEARCH)    /*  進む  */
  1176.             {
  1177.                 pos = 0 ;
  1178.                 lnum = hd->line_num + 1 ;
  1179.  
  1180.                 if( offset > 8 )
  1181.                     lnum++ ;
  1182.             }
  1183.             else                /*  戻る  */
  1184.             {
  1185.                 pos = LINEMAX-1 ;
  1186.                 lnum = hd->line_num + dot->max_y - 2 ;
  1187.                 if (lnum > hd->line_max-1)
  1188.                     lnum = hd->line_max-1;
  1189.  
  1190.                 if( offset < -8 )
  1191.                     lnum-- ;
  1192.             }
  1193.             memcpy( laststr, str, str_len ) ;
  1194.         }
  1195.         else if( lastfunc != func && found == TRUE )
  1196.         {                           /*  途中で方向だけが変わった  */
  1197.             if( func == MEv_fSEARCH )   /*  ↓方向  */
  1198.                 pos += 2  ;
  1199.             else                        /*  ↑方向  */
  1200.                 pos -= str_len+1 ;
  1201.         }
  1202.  
  1203.         mos_ptn(MOSCSR_CLOCK);      /*  時計  */
  1204.         lastcaps = setup.caps;
  1205.         lastfunc = func;
  1206.         forward = (func == MEv_fSEARCH || func == MEv_FfSEARCH) ? TRUE:FALSE;
  1207.         found = FALSE;
  1208.         memcpy(laststr, str, str_len);
  1209.  
  1210.         while (TRUE)
  1211.         {
  1212.             if (pos < 0 || pos >= LINEMAX)      /*  範囲検査  */
  1213.             {
  1214.                 pos = forward ? 0 : LINEMAX-1 ;
  1215.                 if (forward)       /*  進む  */
  1216.                     lnum++;
  1217.                 else                /*  戻る  */
  1218.                     lnum--;
  1219.                 newline = TRUE;
  1220.             }
  1221.  
  1222.             if (lnum < 0 || lnum > hd->line_max-1)
  1223.                 break;
  1224.  
  1225.             if (newline)
  1226.                 lp = &(base[lnum/LINEPTRs]->ptr[lnum%LINEPTRs]);
  1227.  
  1228.             if (forward)
  1229.                 pos = findstr(lp->buf, str,str_len, pos, lp->bytes-pos);
  1230.             else
  1231.                 pos = findrstr(lp->buf, str,str_len, pos, lp->bytes);
  1232.  
  1233.             /*  発見できない  */
  1234.             if (pos < 0 || pos >= LINEMAX)
  1235.                 continue;
  1236.  
  1237.             /*  発見した  */
  1238.             if (newline)
  1239.                 typecheck(type, lp->buf, lp->bytes), newline = FALSE;
  1240.  
  1241.             if (type[pos] == IS_KANJI2)     /*  漢字2バイト目  */
  1242.             {
  1243.                 pos += forward ? 1:-1;
  1244.                 continue;
  1245.             }
  1246.  
  1247.             diff = lnum - hd->line_num;
  1248.  
  1249.             if (lnum <= hd->line_max-1 &&
  1250.                 (diff < 1 || diff > dot->max_y-3 ||
  1251.                                     offset != 0 && (diff == 1)))
  1252.             {
  1253.                 dsp_file(lnum-10 < 0 ? 0 : lnum-10);
  1254.                 redisp_lnum();
  1255.                 DSP_scr_bar(FALSE);
  1256.             }
  1257.  
  1258.             if (offset != 0 && (lnum == 1 || lnum == hd->line_max-1))
  1259.                 dsp_adr_set(vram_ofs + (offset = 0));
  1260.  
  1261.             x  = calc_pos(lp->buf, pos);
  1262.             xs = calc_len(lp->buf, pos, x, str_len);
  1263.             x = x*8 + XMIN, xs *= 8;
  1264.             y = (lnum - hd->line_num ) * dot->font + dot->ofs;
  1265.             line(x, y+vram_ofs, xs);
  1266.             line_lnum = lnum/*, line_lineofs = lnum - hd->line_num + 1 */;
  1267.  
  1268.             if (x >= menu_x && x <= menu_x+size_x &&
  1269.                 y >= menu_y && y <= menu_y+size_y)
  1270.             {
  1271.                 if (y > 240)    menu_y = 0;
  1272.                 else            menu_y = 480;
  1273.                 input_string(str, YES, &menu_x,&menu_y, &size_x,&size_y,
  1274.                                                         &minline,&maxline);
  1275.             }
  1276.             y += vram_ofs;
  1277.  
  1278.             found = TRUE;
  1279.             newline = FALSE;
  1280.             pos += forward ? str_len : -1;
  1281.             break;
  1282.         }
  1283.  
  1284.         /*  みつからない  */
  1285.         if( lnum < 0 || lnum > hd->line_max-1 )
  1286.         {
  1287.             DSP_writePage( gwork, 0 ) ;
  1288.             setup.palette.text.color = 8 ;
  1289.             setup.palette.back.color = 10 ;
  1290.             EGB_palette( gwork, 1, (char *)&setup.palette ) ;
  1291. int     i ;
  1292.             for( i = 0 ; i < 80_000 ; i++ ) ;
  1293.             setup.palette.text.color = 10 ;
  1294.             setup.palette.back.color = 8 ;
  1295.             EGB_palette( gwork, 1, (char *)&setup.palette ) ;
  1296.             DSP_writePage( gwork, 1 ) ;
  1297.         }
  1298.     }
  1299. }
  1300.  
  1301. u_char  char_to_sc[] = {
  1302.     0x1E,  /* A */  0x2E,  /* B */  0x2C,  /* C */  0x20,  /* D */
  1303.     0x13,  /* E */  0x21,  /* F */  0x22,  /* G */  0x23,  /* H */
  1304.     0x18,  /* I */  0x24,  /* J */  0x25,  /* K */  0x26,  /* L */
  1305.     0x30,  /* M */  0x2F,  /* N */  0x19,  /* O */  0x1A,  /* P */
  1306.     0x11,  /* Q */  0x14,  /* R */  0x1F,  /* S */  0x15,  /* T */
  1307.     0x17,  /* U */  0x2D,  /* V */  0x12,  /* W */  0x16,  /* Y */
  1308.     0x2B,  /* X */  0x2A,  /* Z */ };
  1309. u_char  sc_to_char[] = {
  1310.     ' ',' ','1','2','3','4','5','6','7','8','9','0','-','^','\\',' ',
  1311.     ' ','Q','W','E','R','T','Y','U','I','O','P','@','[',' ','A','S',
  1312.     'D','F','G','H','J','K','L',';',':',']','Z','X','C','V','B','N',
  1313.     'M',',','.','/','"' };
  1314. static  keytbl_t    text_key[] = {
  1315.     {0xFF5D, MEv_FULLPATH }, /*  PF1  : メニュー  */
  1316.     {0xFF5E, MEv_FORM     }, /*  PF2  : 書式      */
  1317.     {0xFF5F, MEv_SEARCH   }, /*  PF3  : 検索      */
  1318.     {0xFF60, MEv_DOSCMD   }, /*  PF4  : 外部コマンド  */
  1319.     {0xFF66, MEv_SND      }, /*  PF10 : SND       */
  1320.     {0xFF69, MEv_FS       }, /*  PF11 : FS        */
  1321.     {0xFF5B, MEv_EXIT     }, /*  PF12 : EXIT      */
  1322.     {0xFF11, MEv_EXIT     }, /*  'Q'  : EXIT      */
  1323.     {0xFF01, MEv_EXIT     }, /*  ESC  : EXIT      */
  1324.     {0xFF21, MEv_SEARCH   }, /*  'F'  : 検索      */
  1325.     {0xFF2D, MEv_DISPCR   }, /*  'V'  : 改行文字表示切り換え */
  1326.     {0xFF12, MEv_GOTO_TOP }, /*  'W'  : テキスト先頭へ移動   */
  1327.     {0xFF2A, MEv_GOTO_BTM }, /*  'Z'  : テキスト末尾へ移動   */
  1328.     { 0x013, MEv_sDOWN    }, /*    'E':     逆スクロール     */
  1329.     { 0x113, MEv_mDOWN    }, /*  S+'E': 中速逆スクロール     */
  1330.     { 0x213, MEv_hDOWN    }, /*  C+'E': 高速逆スクロール     */
  1331.     { 0x313, MEv_hDOWN    }, /* SC+'E': 高速逆スクロール     */
  1332.     { 0x02B, MEv_sUP      }, /*    'X':       スクロール     */
  1333.     { 0x12B, MEv_mUP      }, /*  S+'X': 中速  スクロール     */
  1334.     { 0x22B, MEv_hUP      }, /*  C+'X': 高速  スクロール     */
  1335.     { 0x32B, MEv_hUP      }, /* SC+'X': 高速  スクロール     */
  1336.     { 0x04F, MEv_mDOWN    }, /*    ← : 中速逆スクロール     */
  1337.     { 0x14F, MEv_hDOWN    }, /*  S+← : 高速逆スクロール     */
  1338.     { 0x24F, MEv_hDOWN    }, /*  C+← : 高速逆スクロール     */
  1339.     { 0x34F, MEv_hDOWN    }, /* SC+← : 高速逆スクロール     */
  1340.     { 0x04D, MEv_sDOWN    }, /*    ↑ :     逆スクロール     */
  1341.     { 0x14D, MEv_mDOWN    }, /*  S+↑ : 中速逆スクロール     */
  1342.     { 0x24D, MEv_hDOWN    }, /*  C+↑ : 高速逆スクロール     */
  1343.     { 0x34D, MEv_hDOWN    }, /* SC+↑ : 高速逆スクロール     */
  1344.     { 0x051, MEv_mUP      }, /*    → : 中速  スクロール     */
  1345.     { 0x151, MEv_hUP      }, /*  S+→ : 高速  スクロール     */
  1346.     { 0x251, MEv_hUP      }, /*  C+→ : 高速  スクロール     */
  1347.     { 0x351, MEv_hUP      }, /* SC+→ : 高速  スクロール     */
  1348.     { 0x050, MEv_sUP      }, /*    ↓ :       スクロール     */
  1349.     { 0x150, MEv_mUP      }, /*  S+↓ : 中速  スクロール     */
  1350.     { 0x250, MEv_hUP      }, /*  C+↓ : 高速  スクロール     */
  1351.     { 0x350, MEv_hUP      }, /* SC+↓ : 高速  スクロール     */
  1352.     {0xFF6E, MEv_uDOWN    }, /*  前行 : 超高速逆スクロール   */
  1353.     {0xFF70, MEv_uUP      }, /*  次行 : 超高速  スクロール   */
  1354.     {0xFF73, MEv_WIDTH    }, /*  実行 : 画面幅の切り換え     */
  1355.     {    -1, MEv_NULL     }, /*  キーイベント定義おしまい    */
  1356. };
  1357. mevt_t  key_event(int keycode, keytbl_t *kp)
  1358. {
  1359. int        mask, key;
  1360.  
  1361.     if (keycode < 1)
  1362.         return MEv_NULL;
  1363.  
  1364.     while (kp->key > 0)     /* キーアドレスは1以上 */
  1365.     {
  1366.         if ((key = kp->key) & 0xF000)   /* mask ? */
  1367.         {
  1368.             mask = (key >> 4) & 0xF00;
  1369.             key &= 0xFFF;
  1370.         }
  1371.         else
  1372.             mask = 0;
  1373.  
  1374.         if (key == (keycode | mask))
  1375.             return kp->event;
  1376.         kp++;
  1377.     }
  1378.  
  1379.     return MEv_NULL;
  1380. }
  1381.  
  1382.  
  1383. /*  メインループと、その補助サブルーチン  */
  1384.  
  1385. /*
  1386.  *  ファイルセレクタでファイルを選択する
  1387.  *
  1388.  *  この関数から脱出するには、
  1389.  *      1. キャンセル可能状態でキャンセルが選択される
  1390.  *      2. 終了が選択される
  1391.  *      3. ファイルが選択され、そのファイルを読み込むことができた
  1392.  *  このいずれかの状態になったときだけである。
  1393.  *
  1394.  *  関数の戻り値は、この3つの状態を返す
  1395.  *  また、ファイルが選択され、読み込みに成功した場合は、渡されたバッファに
  1396.  *      パスリストを設定する
  1397.  *
  1398.  *  in
  1399.  *      int enable_cancel   : TRUE  -> キャンセル可能
  1400.  *                            FALSE -> キャンセル不可能
  1401.  *      char path[]         : 選択されたファイルのパスリストが格納される
  1402.  *
  1403.  *  out
  1404.  *      -1  : 終了
  1405.  *      0   : キャンセル
  1406.  *      1   : 選択
  1407. */
  1408. int     fs(int enable_cancel, char *path)
  1409. {
  1410. char    *file;
  1411.  
  1412.     while (1)
  1413.     {
  1414.         set_fs_screen();                /* 画面をセットアップ */
  1415.  
  1416.         file = file_select(enable_cancel);  /* ファイルを選択 */
  1417.  
  1418.         if (file == NULL)               /* EXIT: 終了 */
  1419.             return -1;
  1420.  
  1421.         if (*file == '\0')              /* ESC:  取消 */
  1422.         {                               /* キャンセル可能でなければ選べない */
  1423.             return 0;
  1424.         }
  1425.         else                            /* ファイル選択 */
  1426.         {
  1427.             if (read_file(file, FILE_READ, 0) != NULL)  /* 読み込み成功 */
  1428.             {
  1429.                 strncpy(path, file, 254);
  1430.                 return 1;
  1431.             }
  1432.         }
  1433.     }
  1434. }
  1435.  
  1436. void    _dsp_main(char *pathlist)
  1437. {
  1438. const   lines = 2;          /* 高速スクロール時のスクロール行数 */
  1439. int     i, ch, value;
  1440. HEADER  *hd = now_file;
  1441. mevt_t  repeat_evt = MEv_NULL;
  1442. mevt_t  keyon = MEv_NULL;
  1443. int     new_cr = setup.disp_cr;
  1444. int     new_ctrl = setup.disp_ctrl;
  1445. int     new_tab = setup.tabsiz;
  1446. int     new_dpl = setup.dpl_mode;
  1447. int     now_offset = offset;
  1448.  
  1449.     set_wide_screen(OFF);           /*  横幅は拡大せず  */
  1450.     set_screen(MOS_ON);
  1451.  
  1452.     while (1)           /*  テキスト表示状態のメイン・ループ  */
  1453.     {
  1454.         /* 行番号の表示 */
  1455.         redisp_lnum();
  1456.  
  1457.         /* イベント発生待ち */
  1458.         for (i = 0, menu_event = repeat_evt;
  1459.              menu_event == MEv_NULL;
  1460.              EVT_loop(127, 129), i++)
  1461.         {
  1462.             if (i > 256)
  1463.             {
  1464.                 if ((ch = kb_check()) != 0)
  1465.                 {
  1466.                     menu_event = key_event(ch, text_key);
  1467.                 }
  1468.                 if (keyon != MEv_NULL &&
  1469.                     (auto_move == 0 || menu_event != keyon))
  1470.                 {                          /* キーから手を離していたら */
  1471.                     unset_auto_scroll();        /* 自動スクロール停止 */
  1472.                     keyon = MEv_NULL;
  1473.                 }
  1474.  
  1475.                 i = 0;
  1476.  
  1477.                 redisp_lnum();  /*  行番号の表示  */
  1478.             }
  1479.         }
  1480.         repeat_evt = MEv_NULL;
  1481.  
  1482.  
  1483.         /* イベント処理 */
  1484.         switch (menu_event) {
  1485.  
  1486.           case MEv_FS:              /*  [FS] ボタン  */
  1487.             switch (fs(TRUE, pathlist)) {
  1488.               case -1:                      /* 終了 */
  1489.                 return;
  1490.               case 0:                       /* キャンセル */
  1491.                 set_text_screen(hd->line_num);
  1492.                 break;
  1493.               case 1:                       /* ファイル読み込み */
  1494.                 hd = now_file;
  1495.                 break;
  1496.             }
  1497.             break;
  1498.  
  1499.           case MEv_EXIT:            /*  [EXIT] ボタン  */
  1500.             if (check_exit() == 1)
  1501.                 return;
  1502.             break;
  1503.  
  1504.           case MEv_SND:             /*  [音] ボタン  */
  1505.             snd_scrn();
  1506.             while (kb_check() != 0) ;   /* キーから手を離すまで待つ */
  1507.             break;
  1508.  
  1509.           case MEv_vDOWN:           /*  加速度のつく 上矢印  */
  1510.             value = auto_move;
  1511.             if (value == 0)
  1512.                 value = - setup.btn_speed;
  1513.             else if ((value -= 1) == 0)
  1514.                 value -= 1;
  1515.             set_auto_scroll(value); /* 自動スクロール開始 */
  1516.             break;
  1517.  
  1518.           case MEv_vUP:             /*  加速度のつく 下矢印  */
  1519.             if (value == 0)
  1520.                 value = setup.btn_speed;
  1521.             else if ((value += 1) == 0)
  1522.                 value += 1;
  1523.             set_auto_scroll(value); /* 自動スクロール開始 */
  1524.             break;
  1525.  
  1526.           case MEv_FORM:            /*  表示書式の変更  */
  1527.             new_cr = setup.disp_cr;
  1528.             new_ctrl = setup.disp_ctrl;
  1529.             new_tab = setup.tabsiz;
  1530.             new_dpl = setup.dpl_mode;
  1531.             now_offset = offset;
  1532.  
  1533.             select_form(&new_cr, &new_tab, &new_dpl, &new_ctrl);
  1534.  
  1535.             if (new_tab != setup.tabsiz || new_ctrl != setup.disp_ctrl)
  1536.             {                       /* タブか制御文字の処理が変更されたら */
  1537.                 setup.tabsiz = new_tab ;  /* ファイルのリフォームをおこなう */
  1538.                 setup.disp_ctrl = new_ctrl ;
  1539.                 hd = read_file(pathlist, FILE_REFORM, hd->line_num);
  1540.             }
  1541.             if (new_dpl != setup.dpl_mode || new_cr != setup.disp_cr)
  1542.             {               /* 行間隔か改行モードが変更されたら、再表示  */
  1543.                 setup.disp_cr = new_cr;
  1544.                 setup.dpl_mode = new_dpl;
  1545.                 dot = &dots[setup.dpl_mode];
  1546.                 now_offset = offset;
  1547.                 dsp_file(hd->line_num);
  1548.                 vertical_screen(dot->lines);
  1549.                 DSP_scr_bar(TRUE);
  1550.                 offset = now_offset;
  1551.             }
  1552.             break;
  1553.  
  1554.           case MEv_DISPCR:          /*  改行表示の切り換え  */
  1555.             setup.disp_cr = !setup.disp_cr;
  1556.             now_offset = offset;
  1557.             dsp_file(hd->line_num);
  1558.             offset = now_offset;
  1559.             while (kb_check() != 0) ;   /* キーから手を離すまで待つ */
  1560.             break;
  1561.  
  1562.           case MEv_FULLPATH:        /*  フルパスリスト表示  */
  1563.             display_fullpathlist(pathlist);
  1564.             break;
  1565.  
  1566.           case MEv_SEARCH:          /*  文字列検索  */
  1567.             unset_auto_scroll();        /* 自動スクロール停止 */
  1568.             search_str();
  1569.             break;
  1570.  
  1571.           case MEv_DOSCMD:          /*  外部コマンド  */
  1572.             if (excmd_num == 0)
  1573.                 break;
  1574. int     xsiz;
  1575. char    *msg[EXCMD_MAX+1];
  1576. char    keytbl[EXCMD_MAX+1];
  1577.  
  1578.             for (i = 0; i < excmd_num; i++)
  1579.             {
  1580.                 if ((msg[i] = malloc(excmd_len+1)) == NULL)
  1581.                     break;
  1582.                 strcpy(msg[i], formstrL(excmd[i].name, excmd_len));
  1583.                 if (*excmd[i].name >= 'A' && *excmd[i].name <= 'Z')
  1584.                     keytbl[i] = char_to_sc[*excmd[i].name-'A'];
  1585.                 else
  1586.                     keytbl[i] = '\xFF';
  1587.             }
  1588.             keytbl[i] = '\0';
  1589.             msg[i] = NULL;
  1590.  
  1591.             if ((xsiz = excmd_len * 8 + 16) < 100)
  1592.                 xsiz = 100;
  1593.  
  1594.             xsiz = select_drag(EVT_get_node(128, MEv_DOSCMD), TRUE,
  1595.                                                 270,28, xsiz, msg, keytbl);
  1596.  
  1597.             for (i = 0; i < excmd_num; i++)
  1598.                 if (msg[i] != NULL)
  1599.                     free(msg[i]);
  1600.  
  1601.             if (xsiz >= 0 && exec_cmd(xsiz))
  1602.                 set_text_screen(hd->line_num);
  1603.  
  1604.             break;
  1605.  
  1606.           case MEv_WIDTH:           /* 画面幅の変更 */
  1607.             RIGHT_click();              /* 右クリック時と同じイベント */
  1608.             while (kb_check() != 0) ;   /* キーから手を離すまで待つ */
  1609.             break;
  1610.  
  1611.           case MEv_GOTO_TOP:        /* テキスト先頭へ移動 */
  1612.           case MEv_GOTO_BTM:        /* テキスト末尾へ移動 */
  1613.             unset_auto_scroll();        /* 自動スクロール停止 */
  1614.             offset = 0;
  1615.             dsp_adr_set(vram_ofs);
  1616.  
  1617.             if (menu_event == MEv_GOTO_TOP)
  1618.                 i = 0;
  1619.             else if (menu_event == MEv_GOTO_BTM)
  1620.                 if ((i = hd->line_max - dot->max_y + 1) < 0)
  1621.                     i = 0;
  1622.             dsp_file(i);
  1623.             while (kb_check() != 0) ;   /* キーから手を離すまで待つ */
  1624.             break;
  1625.  
  1626.           case MEv_sDOWN:       /*  キーボードによる低速スクロール  */
  1627.           case MEv_mDOWN:       /*  キーボードによる中速スクロール  */
  1628.           case MEv_hDOWN:       /*  キーボードによる高速スクロール  */
  1629.             if (keyon != menu_event)
  1630.             {
  1631.                 value = setup.btn_speed;
  1632.                 switch (menu_event) {
  1633.                   case MEv_mDOWN: value *= 2; break;
  1634.                   case MEv_hDOWN: value *= 4; break;
  1635.                 }
  1636.                 set_auto_scroll(-value);        /* 自動スクロール開始 */
  1637.                 keyon = menu_event;
  1638.             }
  1639.             break;
  1640.  
  1641.           case MEv_sUP:         /*  キーボードによる低速スクロール  */
  1642.           case MEv_mUP:         /*  キーボードによる中速スクロール  */
  1643.           case MEv_hUP:         /*  キーボードによる高速スクロール  */
  1644.             if (keyon != menu_event)
  1645.             {
  1646.                 value = setup.btn_speed;
  1647.                 switch (menu_event) {
  1648.                   case MEv_mUP: value *= 2; break;
  1649.                   case MEv_hUP: value *= 4; break;
  1650.                 }
  1651.                 set_auto_scroll(value); /* 自動スクロール開始 */
  1652.                 keyon = menu_event;
  1653.             }
  1654.             break;
  1655.  
  1656.           case MEv_uUP:         /*  キーボードによる超高速スクロール  */
  1657.           case MEv_uDOWN:       /*  キーボードによる超高速スクロール  */
  1658.             if (auto_move != 0)
  1659.                 unset_auto_scroll();        /* 自動スクロール停止 */
  1660.             if (offset != 0) {
  1661.                 offset = 0;
  1662.                 dsp_adr_set(vram_ofs);
  1663.             }
  1664.  
  1665.             if (menu_event == MEv_uUP) {
  1666.                 i = hd->line_now + (dot->max_y - hd->cur_pos - 1) + lines;
  1667.                 if (i >= hd->line_max)
  1668.                     i = hd->line_max;
  1669.             } else {
  1670.                 if ((i = hd->line_num - lines) < 0)
  1671.                     i = 0;
  1672.             }
  1673.             dsp_scrn(i);
  1674.  
  1675.             if (key_event(kb_check(), text_key) == menu_event)
  1676.                 repeat_evt = menu_event;
  1677.  
  1678.             break;
  1679.         }
  1680.     }
  1681. }
  1682.  
  1683. void    dsp_main(char *file)
  1684. {
  1685. char    pathlist[256];
  1686.  
  1687.     dot = &dots[setup.dpl_mode];
  1688.  
  1689.     if (file != NULL)
  1690.         strcpy(pathlist, file);
  1691.     else
  1692.         pathlist[0] = '\0';
  1693.  
  1694.     if (file == NULL || read_file(file, FILE_READ, 0) == NULL)
  1695.         if (fs(FALSE, pathlist) == -1)  /* 終了 */
  1696.             return;
  1697.  
  1698.     _dsp_main(pathlist);
  1699.  
  1700.     unset_auto_scroll();        /* 自動スクロール停止 */
  1701.  
  1702.     free_head();
  1703.  
  1704.     cls(1, 0);
  1705.     cls(0, 0);
  1706.     set_fs_screen();
  1707. }
  1708.  
  1709.